package com.woniuxy.yoga.product.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.yoga.business.dao.model.BusinessStore;
import com.woniuxy.yoga.commons.core.model.PageInfo;
import com.woniuxy.yoga.commons.core.model.Result;
import com.woniuxy.yoga.commons.core.statedata.BusinessState;
import com.woniuxy.yoga.commons.core.statedata.CoachState;
import com.woniuxy.yoga.commons.core.statedata.CourseState;
import com.woniuxy.yoga.commons.core.statedata.ProductState;
import com.woniuxy.yoga.commons.core.util.DateUtil;
import com.woniuxy.yoga.commons.redis.util.rediskeyutil.ProductRedisKeyUtil;
import com.woniuxy.yoga.product.client.BusinessStoreClient;
import com.woniuxy.yoga.product.client.CoachClient;
import com.woniuxy.yoga.product.client.CourseClient;
import com.woniuxy.yoga.product.client.dto.business.BusinessStoreByAccountIdDTO;
import com.woniuxy.yoga.product.client.dto.business.BusinessStoreDTO;
import com.woniuxy.yoga.product.client.dto.business.StoreClassroomByIdDTO;
import com.woniuxy.yoga.product.client.dto.coach.CoachByIdDTO;
import com.woniuxy.yoga.product.client.dto.course.CourseTypeDTO;
import com.woniuxy.yoga.product.client.dto.course.OrdinaryCourseDTO;
import com.woniuxy.yoga.product.client.form.course.AddTeamCourseForm;
import com.woniuxy.yoga.product.dao.model.TeamProduct;
import com.woniuxy.yoga.product.dao.mapper.TeamProductMapper;
import com.woniuxy.yoga.product.model.dto.AllTeamProductDTO;
import com.woniuxy.yoga.product.model.dto.QueryAllTeamProductDTO;
import com.woniuxy.yoga.product.model.dto.TeamProductDTO;
import com.woniuxy.yoga.product.model.exception.ProductException;
import com.woniuxy.yoga.product.model.exception.ProductExceptionCode;
import com.woniuxy.yoga.product.model.param.AddTeamProductParam;
import com.woniuxy.yoga.product.model.param.QueryTeamProductParam;
import com.woniuxy.yoga.product.service.service.TeamProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 团课产品表 服务实现类
 * </p>
 *
 * @author 韦用文, 刘存益, 郎腾霄
 * @since 2023年11月28日
 */
@Service
public class TeamProductServiceImpl extends ServiceImpl<TeamProductMapper, TeamProduct> implements TeamProductService {

    @Autowired
    private TeamProductMapper teamProductMapper;

    @Autowired
    private BusinessStoreClient businessStoreClient;

    @Autowired
    private CourseClient courseClient;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private CoachClient coachClient;

    /**
     * 用户查询团课产品
     *
     * @param
     * @return
     */
    @Override
    public List<TeamProductDTO> queryNormalTeam() {
        //查询所有未开课的团课信息
        QueryWrapper<TeamProduct> wrapper = new QueryWrapper<>();
        //待开课的团课
        wrapper.eq("team_product_state", ProductState.TEAM_PRODUCT_STATE_WAIT);
        List<TeamProduct> teamProducts = teamProductMapper.selectList(wrapper);
        //判断是否存在数据 集合数据转换
        List<TeamProductDTO> teamProductDTOS = new ArrayList<>();
        if (teamProducts != null && teamProducts.size() > 0) {
            for (TeamProduct teamProduct : teamProducts) {
                //对象转换
                TeamProductDTO teamProductDTO = BeanUtil.toBean(teamProduct, TeamProductDTO.class);
                //门店名称赋值
                Result<BusinessStoreDTO> businessStoreResult = businessStoreClient.selByBusinessStoreId(teamProduct.getStoreId());
                if (businessStoreResult.getCode() != 200)
                    throw new ProductException(businessStoreResult.getCode(), businessStoreResult.getMessage());
                //获取数据
                BusinessStoreDTO businessStore = businessStoreResult.getData();
                teamProductDTO.setStoreName(businessStore.getStoreName());
                //数据保存
                teamProductDTOS.add(teamProductDTO);
            }
        }
        return teamProductDTOS;
    }

    /**
     * 教练ID查询团队产品
     * @param ids
     * @return
     */
    @Override
    public List<AllTeamProductDTO> getByCoachId(List<Integer> ids) {
        QueryWrapper<TeamProduct> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_id",ids.get(0));
        //索引排序
        wrapper.orderByAsc("team_product_id");
        //查询团课产品
        List<TeamProduct> teamProducts = teamProductMapper.selectList(wrapper);
        //集合转换
        List<AllTeamProductDTO> allTeamProductDTOS = BeanUtil.copyToList(teamProducts, AllTeamProductDTO.class);
        return allTeamProductDTOS;
    }

    /**
     * 新增团队产品
     *
     * @param param
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void addTeamProduct(AddTeamProductParam param) throws Exception {
        //先判断开课时间是否是过去的时间
        //1.转localDateTime
        LocalDateTime localDateTime = DateUtil.StringToLocalDateTime(param.getOpenTime());
        //2.转date
        Date date = DateUtil.localDateTimeToDate(localDateTime);
        //开课时间的毫秒数
        long start = date.getTime();
        //当前时间的毫秒数
        long time = new Date().getTime();
        //判断开课时间是否小于等于当前时间
        if (start<=time) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_DATE_TIME_ERROR);
        //通过商家ID获取门店ID
        Result<BusinessStoreByAccountIdDTO> businessStoreByAccountIdDTOResult = businessStoreClient.selBusinessStoreByAccountId(param.getAccountId());
        //判断是否报错
        if (businessStoreByAccountIdDTOResult.getCode()!=200) throw new ProductException(businessStoreByAccountIdDTOResult.getCode(),businessStoreByAccountIdDTOResult.getMessage());
        //获取数据
        BusinessStoreByAccountIdDTO businessStoreByAccountIdDTO = businessStoreByAccountIdDTOResult.getData();
        //判断是否存在
        if (businessStoreByAccountIdDTO==null) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_STORE_ABSENT);
        //判断场馆状态是否异常
        if (businessStoreByAccountIdDTO.getStoreState()== BusinessState.STORE_STATE_DELETE) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_STORE_STATE_ERROR);
        //取出门店ID
        Integer storeId = businessStoreByAccountIdDTO.getStoreId();
        //教练ID转换集合
        List<Integer> ids = new ArrayList<>();
        ids.add(param.getCoachId());
        //通过教练ID查询该教练的普通课程
        if (ids.size()>0){
            Result<List<OrdinaryCourseDTO>> ordinaryByCoachIdResult = courseClient.getOrdinaryByCoachId(ids);
            //判断是否报错
            if (ordinaryByCoachIdResult.getCode()!=200) throw new ProductException(ordinaryByCoachIdResult.getCode(),ordinaryByCoachIdResult.getMessage());
            //获取数据
            List<OrdinaryCourseDTO> ordinaryCourseDTOS = ordinaryByCoachIdResult.getData();
            //当存在数据时 判断时间是否冲突
            if (ordinaryCourseDTOS!=null&&ordinaryCourseDTOS.size()>0){
                //取出传过来的时间
                String openTime = param.getOpenTime();//开课时间
                String endTime = DateUtil.addDaysToString(openTime, param.getHourCount());//结课时间
                //遍历所有普通课程
                for (OrdinaryCourseDTO ordinaryCourseDTO : ordinaryCourseDTOS) {
                    //判断该教练的普通课程状态是否是待开课或者已开课状态
                    if (ordinaryCourseDTO.getCourseState()==CourseState.ORDINARY_COURSE_STATE_WAIT || ordinaryCourseDTO.getCourseState()==CourseState.ORDINARY_COURSE_STATE_START){
                        //取出每节课的开课时间和结课时间
                        String courseStartDate = ordinaryCourseDTO.getCourseStartDate();
                        String courseEndDate = ordinaryCourseDTO.getCourseEndDate();
                        //将时间转换成毫秒
                        long open = DateUtil.convertToMilliseconds(openTime);
                        long end = DateUtil.convertToMilliseconds(endTime);
                        long courseStart = DateUtil.convertToMilliseconds(courseStartDate);
                        long courseEnd = DateUtil.convertToMilliseconds(courseEndDate);
                        //比较时间
                        if ( !((courseStart<open&&courseEnd<open) || (courseStart>end&&courseEnd>end)) ) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_CONFLICT);
                    }
                }
            }
        }
        //通过教练ID查询该教练的团队产品
        QueryWrapper<TeamProduct> wrapper = new QueryWrapper<>();
        wrapper.eq("coach_id",param.getCoachId());
        //索引排序
        wrapper.orderByAsc("team_product_id");
        List<TeamProduct> teamProducts = teamProductMapper.selectList(wrapper);
        if (teamProducts!=null&&teamProducts.size()>0){
            //取出传过来的时间
            String openTime = param.getOpenTime();//开课时间
            String endTime = DateUtil.addDaysToString(openTime, param.getHourCount());//结课时间
            //遍历所有团队产品
            for (TeamProduct teamProduct : teamProducts) {
                //判断该教练的团队课程状态是否是待开课或者是已开课状态
                if (teamProduct.getTeamProductState()==ProductState.TEAM_PRODUCT_STATE_WAIT || teamProduct.getTeamProductState()==ProductState.TEAM_PRODUCT_STATE_START){
                    //取出团队产品的开课时间
                    String newOpenTime = teamProduct.getOpenTime();
                    //通过总课时计算出结课时间 加两个小时
                    String newEndTime = DateUtil.addDaysToString(newOpenTime, teamProduct.getHourCount()-1);
                    String teamEndTime = DateUtil.increaseTwoHour(newEndTime);
                    //将时间转换成毫秒
                    long open = DateUtil.convertToMilliseconds(openTime);
                    long end = DateUtil.convertToMilliseconds(endTime);
                    long newOpen = DateUtil.convertToMilliseconds(newOpenTime);
                    long newEnd = DateUtil.convertToMilliseconds(teamEndTime);
                    //比较时间
                    if ( !((open<newOpen&&end<newOpen) || (open>newEnd&&end>newEnd)) ) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_CONFLICT);
                }
            }
        }
        //判断教室是否报错
        Result<StoreClassroomByIdDTO> storeClassroomByIdDTOResult = businessStoreClient.selNormalByStoreClassroomId(param.getClassroomId());
        if (storeClassroomByIdDTOResult.getCode()!=200) throw new ProductException(storeClassroomByIdDTOResult.getCode(),storeClassroomByIdDTOResult.getMessage());
        //获取数据
        StoreClassroomByIdDTO storeClassroomByIdDTO = storeClassroomByIdDTOResult.getData();
        //判断是否存在
        if (storeClassroomByIdDTO==null) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_CLASS_ROOM_NOT_EXIST);
        //判断教室状态是否异常
        if (storeClassroomByIdDTO.getClassroomState()!=BusinessState.CLASSROOM_STATE_NORMAL) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_CLASS_ROOM_STATE_ERROR);
        //判断该教室是否是团队教室
        if (storeClassroomByIdDTO.getClassroomType()==0) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_CLASS_ROOM_IS_ORDINARY);
        //判断团课产品最大人数不能大于教室人数
        if (param.getTeamMax()>storeClassroomByIdDTO.getClassroomMax()) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_MAX_COUNT_NOT_GT_CLASS_ROOM_MAX_COUNT);
        //通过教练ID查询教练信息
        Result<CoachByIdDTO> coachByIdDTOResult = coachClient.getCoachById(param.getCoachId());
        if (coachByIdDTOResult.getCode()!=200) throw new ProductException(coachByIdDTOResult.getCode(),coachByIdDTOResult.getMessage());
        //获取数据
        CoachByIdDTO coachByIdDTO = coachByIdDTOResult.getData();
        //判断是否存在
        if (coachByIdDTO==null) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_COACH_NOT_EXIST);
        //判断教练状态是否异常
        if (coachByIdDTO.getCoachState()!= CoachState.COACH_STATE_NORMAL) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_COACH_STATE_ERROR);
        //对象转换
        TeamProduct teamProduct = BeanUtil.toBean(param, TeamProduct.class);
        //教练名称赋值
        teamProduct.setCoachName(coachByIdDTO.getCoachName());
        //课程类型ID赋值
        teamProduct.setCourseTypeId(CourseState.TEAM_COURSE_TYPE_ID);
        //课程类型赋值
        teamProduct.setCourseTypeName(CourseState.TEAM_COURSE_TYPE_NAME);
        //门店ID赋值
        teamProduct.setStoreId(storeId);
        //团课状态赋值
        teamProduct.setTeamProductState(ProductState.TEAM_PRODUCT_STATE_WAIT);
        //新增团队产品
        teamProductMapper.insertTeamProduct(teamProduct);
        //准备对象赋值
        AddTeamCourseForm addTeamCourseForm = new AddTeamCourseForm();
        addTeamCourseForm.setTeamProductId(teamProduct.getTeamProductId());
        addTeamCourseForm.setTeamProductName(param.getTeamProductName());
        addTeamCourseForm.setStoreId(storeId);
        addTeamCourseForm.setCoachId(param.getCoachId());
        addTeamCourseForm.setClassroomId(param.getClassroomId());
        addTeamCourseForm.setStartTime(param.getOpenTime());
        addTeamCourseForm.setEndTime(DateUtil.addDaysToString(param.getOpenTime(),param.getHourCount()));
        //调用新增团队课程
        Result<?> result = courseClient.addTeamCourse(addTeamCourseForm);
        if (result.getCode()!=200) throw new ProductException(result.getCode(),result.getMessage());
        //设置定时任务 到时自动将状态修改成已开课 创建json数据
        Map<String, Object> map = new HashMap<>();
        map.put("teamProductId",teamProduct.getTeamProductId());
        //转json字符串
        String teamProductId = JSONUtil.toJsonStr(map);
        //设置定时任务
        String xxlLoginAPI="http://192.168.90.27:9999/xxl-job-admin/login";
        String xxlAddJobAPI="http://192.168.90.27:9999/xxl-job-admin/jobinfo/add";
        HashMap<String, Object> loginParam = new HashMap<String,Object>();
        loginParam.put("userName", "admin");
        loginParam.put("password", "123456");
        HttpResponse httpResponse = HttpRequest.post(xxlLoginAPI).form(loginParam).execute();
        if(httpResponse.getStatus()!=200) {
            throw new Exception("登录失败");
        }
        Map<String, Object> addTaskParam = new HashMap<String,Object>();
//        LocalDateTime now = LocalDateTime.now();
        //设置多久发一次
//        LocalDateTime executeTime = now.plusMinutes(1);
//        int year = executeTime.get(ChronoField.YEAR);
//        int month = executeTime.get(ChronoField.MONTH_OF_YEAR);
//        int day = executeTime.get(ChronoField.DAY_OF_MONTH);
//        int hour=executeTime.get(ChronoField.HOUR_OF_DAY);
//        int minute=executeTime.get(ChronoField.MINUTE_OF_HOUR);
//        int second=executeTime.get(ChronoField.SECOND_OF_MINUTE);
        StringBuilder cron = new StringBuilder();
        cron.append("0 0 15 * * ? *");
//        cron.append(" "+minute);
//        cron.append(" "+hour);
//        cron.append(" "+day);
//        cron.append(" "+month);
//        cron.append(" ?");
//        cron.append(" "+year);
        addTaskParam.put("jobGroup", 5);
        addTaskParam.put("scheduleConf", cron.toString());
        addTaskParam.put("jobDesc", "团课开课时间启动");
        addTaskParam.put("author", "韦用文");
        addTaskParam.put("executorHandler", "teamProductExpire");
        addTaskParam.put("executorParam",teamProductId);//团队产品ID
        addTaskParam.put("scheduleType", "CRON");
        addTaskParam.put("executorRouteStrategy", "FIRST");
        addTaskParam.put("executorBlockStrategy", "SERIAL_EXECUTION");
        addTaskParam.put("glueType", "BEAN");
        addTaskParam.put("misfireStrategy","DO_NOTHING");
        addTaskParam.put("executorTimeout", "0");
        addTaskParam.put("executorFailRetryCount","0");
        addTaskParam.put("triggerStatus", 1);
        HttpResponse response = HttpRequest.post(xxlAddJobAPI).form(addTaskParam).execute();
    }

    /**
     * 团队产品取消(线下退款)
     * @param teamProductId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelTeamProduct(Integer teamProductId) {
        TeamProduct teamProduct = teamProductMapper.selectById(teamProductId);
        //判断是否存在团队产品
        if (teamProduct==null) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_NOT_EXIST);
        //判断团队产品状态是否是待开课
        if (teamProduct.getTeamProductState()!=ProductState.TEAM_PRODUCT_STATE_WAIT) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_STATE_ERROR);
        //修改团队产品状态
        teamProduct.setTeamProductState(ProductState.TEAM_PRODUCT_STATE_CANCEL);
        teamProductMapper.updateById(teamProduct);
    }

    /**
     * 团队产品完成
     * @param teamProductId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeTeamProduct(Integer teamProductId) {
        TeamProduct teamProduct = teamProductMapper.selectById(teamProductId);
        //判断是否存在
        if (teamProduct==null) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_NOT_EXIST);
        //判断团队产品状态是否异常
        if (teamProduct.getTeamProductState()!=ProductState.TEAM_PRODUCT_STATE_START) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_STATE_ERROR);
        //先获取结课时间
        String endTime = DateUtil.addDaysToString(teamProduct.getOpenTime(), teamProduct.getHourCount());
        //获取具体毫秒数
        long endSecond = DateUtil.convertToMilliseconds(endTime);
        //加两个小时的结束时间
        long addSecond = 2*60*60*1000L;
        //最终结课时间
        long finalSecond = endSecond + addSecond;
        //获取当前时间的毫秒数
        long currentSecond = new Date().getTime();
        //判断当前时间是否大于等于最终结课时间
        if (currentSecond<finalSecond) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_COURSE_NOT_OVER);
        //修改成已完成状态
        teamProduct.setTeamProductState(ProductState.TEAM_PRODUCT_STATE_COMPLETE);
        teamProductMapper.updateById(teamProduct);
    }

    /**
     * 商家查询自己的所有团队产品
     * @param param
     * @return
     */
    @Override
    public PageInfo queryTeamProduct(QueryTeamProductParam param) {
        QueryWrapper<TeamProduct> wrapper = new QueryWrapper<>();
        //当前商家的所有产品
        wrapper.eq("store_id",param.getStoreId());
        //团课产品名搜索
        if (ObjectUtil.isNotEmpty(param.getTeamProductName())){
            wrapper.like("team_product_name",param.getTeamProductName());
        }
        //教练名称搜索
        if (ObjectUtil.isNotEmpty(param.getCoachName())){
            wrapper.like("coach_name",param.getCoachName());
        }
        //课程类别ID搜索
        if (ObjectUtil.isNotEmpty(param.getCourseTypeId())){
            wrapper.eq("course_type_id",param.getCourseTypeId());
        }
        //团队产品最低价格搜索
        if (ObjectUtil.isNotEmpty(param.getTeamProductPriceMin())){
            wrapper.ge("team_product_price",param.getTeamProductPriceMin());
        }
        //团队产品最高价格搜索
        if (ObjectUtil.isNotEmpty(param.getTeamProductPriceMax())){
            wrapper.le("team_product_price",param.getTeamProductPriceMax());
        }
        //团课状态搜索
        if (ObjectUtil.isNotEmpty(param.getTeamProductState())){
            wrapper.eq("team_product_state",param.getTeamProductState());
        }
        //索引排序
        wrapper.orderByAsc("team_product_id");
        //分页查询
        Page<TeamProduct> page = new Page<>(param.getPageNum() == null ? 1 : param.getPageNum(), param.getPageSize() == null ? 5 : param.getPageSize());
        teamProductMapper.selectPage(page,wrapper);
        //集合转换
        List<QueryAllTeamProductDTO> queryAllTeamProductDTOS = new ArrayList<>();
        if (page.getRecords()!=null&&page.getRecords().size()>0){
            for (TeamProduct teamProduct : page.getRecords()) {
                //对象转换
                QueryAllTeamProductDTO queryAllTeamProductDTO = BeanUtil.toBean(teamProduct, QueryAllTeamProductDTO.class);
                //门店名称赋值
                Result<BusinessStoreDTO> businessStoreResult = businessStoreClient.selByBusinessStoreId(teamProduct.getStoreId());
                //获取数据
                BusinessStoreDTO businessStore = businessStoreResult.getData();
                queryAllTeamProductDTO.setStoreName(businessStore.getStoreName());
                //团课状态赋值
                queryAllTeamProductDTO.setTeamProductState(teamProduct.getTeamProductState()==0?"待开课":teamProduct.getTeamProductState()==1?"已开课":teamProduct.getTeamProductState()==2?"已取消":"已完成");
                //数据保存
                queryAllTeamProductDTOS.add(queryAllTeamProductDTO);
            }
        }
        //分页对象转换
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setPages(page.getPages());
        pageInfo.setRecords(queryAllTeamProductDTOS);
        return pageInfo;
    }

    /**
     * 修改预约人数
     * @param teamProductId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyBookNum(Integer teamProductId) throws Exception {
        //创建分布式锁
        RLock lock = redissonClient.getFairLock(ProductRedisKeyUtil.lockBookNumByTeamProductId(teamProductId));
        boolean isLock = lock.tryLock(10, TimeUnit.SECONDS);
        try {
            if (!isLock){
                throw new Exception("服务器繁忙请稍后再试");
            }
            TeamProduct teamProduct = teamProductMapper.selectById(teamProductId);
            //判断是否存在
            if (teamProduct==null) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_NOT_EXIST);
            //判断团队产品状态是否是待开课状态
            if (teamProduct.getTeamProductState()!=ProductState.TEAM_PRODUCT_STATE_WAIT) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_STATE_ERROR);
            //判断已预约人数数量是否大于等于最大人数数量
            Integer bookNum = teamProduct.getBookNum();//已预约人数
            Integer teamMax = teamProduct.getTeamMax();//最大人数
            if (bookNum>=teamMax) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_BOOK_NUM_UPPER_LIMIT);
            //预约人数加一
            teamProduct.setBookNum(teamProduct.getBookNum()+1);
            teamProductMapper.updateById(teamProduct);
        }finally {
            //判断是否是自己的锁 并且是还未释放
            if (lock.isLocked()){
                lock.unlock();
            }
        }
    }

    /**
     * 团队产品总天数减一
     * @param teamProductId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer hourCountMinusOne(Integer teamProductId) {
        TeamProduct teamProduct = teamProductMapper.selectById(teamProductId);
        //判断是否存在
        if (teamProduct==null) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_NOT_EXIST);
        //判断团队产品状态是否异常(已开课)
        if (teamProduct.getTeamProductState()!=ProductState.TEAM_PRODUCT_STATE_START) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_STATE_ERROR);
        //判断团队产品总天数是否还能减
        if (teamProduct.getHourCount()<1) throw new ProductException(ProductExceptionCode.PRODUCT_EXCEPTION_CODE_TEAM_PRODUCT_HOUR_COUNT_COMPLETE);
        //团队产品总天数减一
        teamProduct.setHourCount(teamProduct.getHourCount()-1);
        teamProductMapper.updateById(teamProduct);
        //返回减一之后的数量
        return teamProduct.getHourCount()-1;
    }
}
